package handler

import (
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"net/http"
	v1 "server_go/api/v1"
	"server_go/internal/service"
)

type ArticleHandler interface {
	AddArticle(ctx *gin.Context)
	DeleteArticle(ctx *gin.Context)
	UpdateArticle(ctx *gin.Context)
	GetArticleProfile(ctx *gin.Context)
	GetAllArticle(ctx *gin.Context)
	GetAllArticleList(ctx *gin.Context)
	GetArticleByTagId(ctx *gin.Context)
	GetArticleByUserId(ctx *gin.Context)
	GetArticleByTitle(ctx *gin.Context)
}

type articleHandler struct {
	*Handler
	articleService service.ArticleService
}

func NewArticleHandler(
	handler *Handler,
	articleService service.ArticleService,
) ArticleHandler {
	return &articleHandler{
		Handler:        handler,
		articleService: articleService,
	}
}

func (h *articleHandler) AddArticle(ctx *gin.Context) {
	req := new(v1.AddArticleRequest)
	if err := ctx.ShouldBind(&req); err != nil {
		h.logger.Error("params error", zap.Any("error", err))
		v1.HandleError(ctx, http.StatusBadRequest, v1.ErrBadRequest, nil)
		return
	}

	h.logger.Info("AddArticle Information")

	if err := h.articleService.AddArticle(req); err != nil {
		v1.HandleError(ctx, http.StatusInternalServerError, err, nil)
		return
	}

	v1.HandleSuccess(ctx, nil)
}

func (h *articleHandler) DeleteArticle(ctx *gin.Context) {
	req := new(v1.DeleteArticleRequest)
	if err := ctx.ShouldBindUri(req); err != nil {
		h.logger.Error("params error", zap.Any("error", err))
		v1.HandleError(ctx, http.StatusBadGateway, v1.ErrBadGateway, nil)
		return
	}

	h.logger.Info("DeleteArticle Information")

	resp, err := h.articleService.DeleteArticle(ctx, req)
	if err != nil {
		v1.HandleError(ctx, http.StatusInternalServerError, err, nil)
		return
	}

	v1.HandleSuccess(ctx, resp)
}

func (h *articleHandler) UpdateArticle(ctx *gin.Context) {
	req := new(v1.UpdateArticleRequest)
	if err := ctx.ShouldBind(req); err != nil {
		h.logger.Error("params error", zap.Any("error", err), zap.Any("req", req))
		v1.HandleError(ctx, http.StatusBadGateway, v1.ErrBadGateway, nil)
		return
	}

	h.logger.Info("UpdateArticle Information")

	if err := h.articleService.UpdateArticle(req); err != nil {
		v1.HandleError(ctx, http.StatusInternalServerError, err, nil)
		return
	}

	v1.HandleSuccess(ctx, nil)
}

func (h *articleHandler) GetArticleProfile(ctx *gin.Context) {
	req := new(v1.GetArticleProfileRequest)
	if err := ctx.ShouldBindUri(req); err != nil {
		h.logger.Error("params error", zap.Any("error", err))
		v1.HandleError(ctx, http.StatusBadRequest, v1.ErrBadRequest, nil)
		return
	}
	resp, err := h.articleService.GetArticleById(req)
	if err != nil {
		v1.HandleError(ctx, http.StatusInternalServerError, err, nil)
		return
	}

	v1.HandleSuccess(ctx, resp)
}

func (h *articleHandler) GetAllArticle(ctx *gin.Context) {
	req := new(v1.GetAllArticleRequest)
	if err := ctx.ShouldBind(&req); err != nil {
		h.logger.Error("params error", zap.Any("error", err))
		v1.HandleError(ctx, http.StatusBadRequest, v1.ErrBadRequest, nil)
		return
	}

	h.logger.Info("GetAllArticle Information")

	resp, err := h.articleService.GetAllArticle(req)

	if err != nil {
		v1.HandleError(ctx, http.StatusInternalServerError, err, nil)
		return
	}

	v1.HandleSuccess(ctx, resp)
}

func (h *articleHandler) GetAllArticleList(ctx *gin.Context) {
	req := new(v1.GetAllArticleRequest)
	if err := ctx.ShouldBind(&req); err != nil {
		h.logger.Error("params error", zap.Any("error", err))
		v1.HandleError(ctx, http.StatusBadRequest, v1.ErrBadRequest, nil)
		return
	}

	h.logger.Info("GetAllArticle Information")

	resp, err := h.articleService.GetAllArticleList(req)

	if err != nil {
		v1.HandleError(ctx, http.StatusInternalServerError, err, nil)
		return
	}

	v1.HandleSuccess(ctx, resp)
}

func (h *articleHandler) GetArticleByTagId(ctx *gin.Context) {
	req := new(v1.GetArticleByTagIdRequest)

	if err := ctx.ShouldBindUri(req); err != nil {
		h.logger.Error("params error", zap.Any("error", err))
		v1.HandleError(ctx, http.StatusBadRequest, v1.ErrBadRequest, nil)
		return
	}

	if err := ctx.ShouldBind(&req); err != nil {
		h.logger.Error("params error", zap.Any("error", err))
		v1.HandleError(ctx, http.StatusBadRequest, v1.ErrBadRequest, nil)
		return
	}

	h.logger.Info("GetArticleByTagId Information", zap.Any("req", req))

	resp, err := h.articleService.GetArticleByTagId(req)

	if err != nil {
		v1.HandleError(ctx, http.StatusInternalServerError, err, nil)
		return
	}

	v1.HandleSuccess(ctx, resp)
}

func (h *articleHandler) GetArticleByUserId(ctx *gin.Context) {
	req := new(v1.GetArticleByUserIdRequest)

	if err := ctx.ShouldBindUri(req); err != nil {
		h.logger.Error("params error", zap.Any("error", err))
		v1.HandleError(ctx, http.StatusBadRequest, v1.ErrBadRequest, nil)
		return
	}

	if err := ctx.ShouldBind(&req); err != nil {
		h.logger.Error("params error", zap.Any("error", err))
		v1.HandleError(ctx, http.StatusBadRequest, v1.ErrBadRequest, nil)
		return
	}

	h.logger.Info("GetArticleByUserId Information", zap.Any("req", req))

	resp, err := h.articleService.GetArticleByUserId(req)

	if err != nil {
		v1.HandleError(ctx, http.StatusInternalServerError, err, nil)
		return
	}

	v1.HandleSuccess(ctx, resp)
}

func (h *articleHandler) GetArticleByTitle(ctx *gin.Context) {
	req := new(v1.GetArticleByTitleReq)

	if err := ctx.ShouldBind(&req); err != nil {
		h.logger.Error("params error", zap.Any("error", err))
		v1.HandleError(ctx, http.StatusBadRequest, v1.ErrBadRequest, nil)
		return
	}

	h.logger.Info("GetArticleByTitle Information", zap.Any("req", req))

	resp, err := h.articleService.GetArticleByTitle(req)

	if err != nil {
		v1.HandleError(ctx, http.StatusInternalServerError, err, nil)
		return
	}

	v1.HandleSuccess(ctx, resp)

}
